home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
c
/
mkproto.exe
/
MKPROTOH.C
< prev
next >
Wrap
Text File
|
1993-04-29
|
13KB
|
699 lines
/* VERSION=#(#):8,596,0, $*/
#include <stddef.h>
#include <stdlib.h>
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#include <malloc.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
FILE *fOut=stdout;
static char szHdr[]="\n"\
"/*****************************************************************************\n"\
" * %-10s \n"\
" ****************************************************************************/\n\n";
#define ISCSYM(x) ((x) > 0 && (isalnum(x) || (x) == '_'))
#define ABORTED ( (Word *) -1 )
#define MAXPARAM 20 /* max. number of parameters to a function */
#define NEWBUFSIZ (20480*sizeof(char)) /* new buffer size */
int inquote = 0; /* in a quote?? */
int newline_seen = 1; /* are we at the start of a line */
long linenum = 1L; /* line number in current file */
int dostatic = 0; /* do static functions? */
int dohead = 1; /* do file headers? */
int glastc = ' '; /* last char. seen by getsym() */
typedef struct word
{
struct word *next;
char string[1];
} Word;
#include "mkprotoh.h"
/*
* Routines for manipulating lists of words.
*/
Word *word_alloc(s)
char *s;
{
Word *w;
w = (Word *) malloc(sizeof(Word) + strlen(s) + 1); /* ++jrb */
strcpy(w->string, s);
w->next = NULL;
return w;
}
void word_free(w)
Word *w;
{
Word *oldw;
while (w)
{
oldw = w;
w = w->next;
free(oldw);
}
}
/* return the length of a list; empty words are not counted */
int
List_len(w)
Word *w;
{
int count = 0;
while (w)
{
if (*w->string) count++;
w = w->next;
}
return count;
}
/* Append two lists, and return the result */
Word *word_append(w1, w2)
Word *w1, *w2;
{
Word *r, *w;
r = w = word_alloc("");
while (w1)
{
w->next = word_alloc(w1->string);
w = w->next;
w1 = w1->next;
}
while (w2)
{
w->next = word_alloc(w2->string);
w = w->next;
w2 = w2->next;
}
return r;
}
/* see if the last entry in w2 is in w1 */
int
foundin(w1, w2)
Word *w1, *w2;
{
while (w2->next)
w2 = w2->next;
while (w1)
{
if (!strcmp(w1->string, w2->string))
return 1;
w1 = w1->next;
}
return 0;
}
/* add the string s to the given list of words */
void addword(w, s)
Word *w;
char *s;
{
while (w->next) w = w->next;
w->next = word_alloc(s);
}
/* given a list representing a type and a variable name, extract just
* the base type, e.g. "struct word *x" would yield "struct word"
*/
Word *typelist(p)
Word *p;
{
Word *w, *r;
r = w = word_alloc("");
while (p && p->next)
{
if (p->string[0] && !ISCSYM(p->string[0]))
break;
w->next = word_alloc(p->string);
w = w->next;
p = p->next;
}
return r;
}
/* typefixhack: promote formal parameters of type "char", "unsigned char",
"short", or "unsigned short" to "int".
*/
void typefixhack(w)
Word *w;
{
Word *oldw = 0;
while (w)
{
if (*w->string)
{
if ( (!strcmp(w->string, "char") ||
!strcmp(w->string, "short") )
&& (List_len(w->next) < 2) )
{
if (oldw && !strcmp(oldw->string, "unsigned"))
{
oldw->next = w->next;
free(w);
w = oldw;
}
strcpy(w->string, "int");
}
}
w = w->next;
}
}
/* read a character: if it's a newline, increment the line count */
int ngetc(f)
FILE *f;
{
int c;
c = getc(f);
if (c == '\n') linenum++;
return c;
}
/* read the next character from the file. If the character is '\' then
* read and skip the next character. Any comment sequence is converted
* to a blank.
*/
int fnextch(f)
FILE *f;
{
int c, lastc, incomment;
c = ngetc(f);
while (c == '\\')
{
c = ngetc(f); /* skip a character */
c = ngetc(f);
}
if (c == '/' && !inquote)
{
c = ngetc(f);
if (c == '*')
{
incomment = 1;
c = ' ';
while (incomment)
{
lastc = c;
c = ngetc(f);
if (lastc == '*' && c == '/')
incomment = 0;
else if (c < 0)
return c;
}
return fnextch(f);
}
else
if(c=='/')
{
incomment = 1;
while (incomment)
{
c = ngetc(f);
if(c=='\n')
{
incomment = 0;
linenum--;
}
else if (c < 0)
return c;
}
return fnextch(f);
}
else
{
if (c == '\n') linenum--;
ungetc(c, f);
return '/';
}
}
return c;
}
/* Get the next "interesting" character. Comments are skipped, and strings
* are converted to "0". Also, if a line starts with "#" it is skipped.
*/
int nextch(f)
FILE *f;
{
int c;
c = fnextch(f);
if (newline_seen && c == '#')
{
do
{
c = fnextch(f);
}
while (c >= 0 && c != '\n');
if (c < 0)
return c;
}
newline_seen = (c == '\n');
if (c == '\'' || c == '\"')
{
inquote = c;
while ( (c = fnextch(f)) >= 0 )
{
if (c == inquote)
{
inquote = 0;
return '0';
}
}
}
return c;
}
/*
* Get the next symbol from the file, skipping blanks.
* Return 0 if OK, -1 for EOF.
* Also collapses everything between { and
}
*/
int
getsym(buf, f)
char *buf;
FILE *f;
{
register int c;
int inbrack = 0;
c = glastc;
while ((c > 0) && isspace(c))
{
c = nextch(f);
}
if (c < 0)
{
return -1;
}
if (c == '{')
{
inbrack = 1;
while (inbrack)
{
c = nextch(f);
if (c < 0)
{
glastc = c;
return c;
}
if (c == '{') inbrack++;
else if (c == '}') inbrack--;
}
strcpy(buf, "{}");
glastc = nextch(f);
return 0;
}
if (!ISCSYM(c))
{
*buf++ = c;
*buf = 0;
glastc = nextch(f);
return 0;
}
while (ISCSYM(c))
{
*buf++ = c;
c = nextch(f);
}
*buf = 0;
glastc = c;
return 0;
}
/*
* skipit: skip until a ";" or the end of a function declaration is seen
*/
int skipit(buf, f)
char *buf;
FILE *f;
{
int i;
do
{
i = getsym(buf, f);
if (i < 0) return i;
}
while (*buf != ';' && *buf != '{');
return 0;
}
/*
* Get a parameter list; when this is called the next symbol in line
* should be the first thing in the list.
*/
Word *getparamlist(f)
FILE *f;
{
static Word *pname[MAXPARAM]; /* parameter names */
Word *tlist, /* type name */
*plist; /* temporary */
int np = 0; /* number of parameters */
int typed[MAXPARAM]; /* parameter has been given a type */
int tlistdone; /* finished finding the type name */
int sawsomething;
int i;
int inparen = 0;
char buf[80];
for (i = 0; i < MAXPARAM; i++)
typed[i] = 0;
plist = word_alloc("");
/* first, get the stuff inside brackets (if anything) */
sawsomething = 0; /* gets set nonzero when we see an arg */
for (;;)
{
if (getsym(buf, f) < 0) return NULL;
if (*buf == ')' && (--inparen < 0))
{
if (sawsomething) { /* if we've seen an arg */
pname[np] = plist;
plist = word_alloc("");
np++;
}
break;
}
if (*buf == ';') { /* something weird */
return ABORTED;
}
sawsomething = 1; /* there's something in the arg. list */
if (*buf == ',' && inparen == 0)
{
pname[np] = plist;
plist = word_alloc("");
np++;
}
else
{
addword(plist, buf);
if (*buf == '(') inparen++;
}
}
/* next, get the declarations after the function header */
inparen = 0;
tlist = word_alloc("");
plist = word_alloc("");
tlistdone = 0;
sawsomething = 0;
for(;;)
{
if (getsym(buf, f) < 0) return NULL;
/* handle a list like "int x,y,z" */
if (*buf == ',' && !inparen)
{
if (!sawsomething)
return NULL;
for (i = 0; i < np; i++)
{
if (!typed[i] && foundin(plist, pname[i]))
{
typed[i] = 1;
word_free(pname[i]);
pname[i] = word_append(tlist, plist);
/* promote types */
typefixhack(pname[i]);
break;
}
}
if (!tlistdone)
{
tlist = typelist(plist);
tlistdone = 1;
}
word_free(plis